/*
** Xin YUAN, 2024, BSD (2)
*/

////////////////////////////////////////////////////////////////////////////////

class WorkData : public CTL::WorkDataBase
{
public:
	WorkData() noexcept : m_v(0)
	{
	}

	const uint32_t& V() const noexcept
	{
		return m_v;
	}
	uint32_t& V() noexcept
	{
		return m_v;
	}

private:
	uint32_t m_v;
};

#define DATA_NUM  (1000)

class TaskTest : public CTL::TaskImpl<TaskTest>
{
private:
	typedef CTL::TaskImpl<TaskTest>  baseClass;

public:
	bool Initialize() noexcept
	{
		if ( !m_data.SetSize(DATA_NUM) )
			return false;
		if ( !m_result_mutex.IsValid() ) {
			if ( !m_result_mutex.Init() )
				return false;
		}
		if ( !baseClass::Initialize() )
			return false;
		for( int i = 0; i < DATA_NUM; i ++ ) {
			call_constructor(m_data[i]);
			m_data[i].V() = i;
		}
		m_total = 0;
		return true;
	}

	int Exec() noexcept
	{
		for( int i = 0; i < DATA_NUM; i ++ ) {
			if ( !baseClass::SubmitWork(&m_data[i]) ) {
				outputf_s(_s("test_task: submit failed [%d]\n"), i);
				return -1;
			}
		}
		return 0;
	}

	uint32_t GetTotal() const noexcept
	{
		uint32_t v;
		m_result_mutex.Lock();
		v = m_total;
		m_result_mutex.Unlock();
		return v;
	}

//overriders
	void DoWork(work_data_base* p) noexcept
	{
		WorkData* pd = (WorkData*)p;
		m_result_mutex.Lock();
		m_total ++;
		outputf_s(_s("test_task: v=%u t=%u\n"), pd->V(), m_total);
		m_result_mutex.Unlock();
	}

private:
	CTL::PlainArray<WorkData> m_data;
	volatile uint32_t m_total;
	mutable sync_mutex m_result_mutex;
};

int test_task() noexcept
{
	outputf_s(_s("==========test_task===========\n"));

	TaskTest tt;
	if ( !tt.Initialize() ) {
		outputf_s(_s("test_task: init failed\n"));
		return 1;
	}
	int ret = tt.Exec();
	while ( tt.GetTotal() < DATA_NUM )
		thread_sleep(1);
	tt.Shutdown();
	outputf_s(_s("test_task: total=%u\n"), tt.GetTotal());

	outputf_s(_s("**********test_task***********\n"));
	return ret;
}

////////////////////////////////////////////////////////////////////////////////
